home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Samples / C++ / Direct3D / HLSLWithoutEffects / HLSLwithoutEffects.cpp next >
Encoding:
C/C++ Source or Header  |  2004-09-27  |  26.2 KB  |  587 lines

  1. //--------------------------------------------------------------------------------------
  2. // File: HLSLwithoutEffects.cpp
  3. //
  4. // Desc: Sample showing a simple vertex shader in D3DX High Level Shader
  5. //       Language (HLSL) without using an ID3DXEffect interface.  Not using the 
  6. //       ID3DXEffect interface is a more difficult method of using HLSL.  See
  7. //       the BasicHLSL sample for a simpler method of using HLSL.
  8. //
  9. // Copyright (c) Microsoft Corporation. All rights reserved.
  10. //--------------------------------------------------------------------------------------
  11. #include "dxstdafx.h"
  12. #include "resource.h"
  13.  
  14. //#define DEBUG_VS   // Uncomment this line to debug vertex shaders 
  15. //#define DEBUG_PS   // Uncomment this line to debug pixel shaders 
  16.  
  17.  
  18. //--------------------------------------------------------------------------------------
  19. // Defines
  20. //--------------------------------------------------------------------------------------
  21. #define VERTS_PER_EDGE 64
  22.  
  23.  
  24. //--------------------------------------------------------------------------------------
  25. // Global variables
  26. //--------------------------------------------------------------------------------------
  27. ID3DXFont*              g_pFont = NULL;         // Font for drawing text
  28. ID3DXSprite*            g_pTextSprite = NULL;   // Sprite for batching draw text calls
  29. CModelViewerCamera      g_Camera;               // A model viewing camera
  30. bool                    g_bShowHelp = true;     // If true, it renders the UI control text
  31. CDXUTDialog             g_HUD;                  // dialog for standard controls
  32.  
  33. // Scene
  34. LPDIRECT3DVERTEXBUFFER9      g_pVB = NULL;
  35. LPDIRECT3DINDEXBUFFER9       g_pIB = NULL;
  36. DWORD                        g_dwNumVertices = VERTS_PER_EDGE * VERTS_PER_EDGE;
  37. DWORD                        g_dwNumIndices = 6 * (VERTS_PER_EDGE - 1) * (VERTS_PER_EDGE - 1);
  38. LPDIRECT3DVERTEXSHADER9      g_pVertexShader = NULL;
  39. LPD3DXCONSTANTTABLE          g_pConstantTable = NULL;
  40. LPDIRECT3DVERTEXDECLARATION9 g_pVertexDeclaration = NULL;
  41.  
  42.  
  43. //--------------------------------------------------------------------------------------
  44. // UI control IDs
  45. //--------------------------------------------------------------------------------------
  46. #define IDC_TOGGLEFULLSCREEN    1
  47. #define IDC_TOGGLEREF           3
  48. #define IDC_CHANGEDEVICE        4
  49.  
  50.  
  51.  
  52. //--------------------------------------------------------------------------------------
  53. // Forward declarations 
  54. //--------------------------------------------------------------------------------------
  55. bool    CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat, bool bWindowed );
  56. void    CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps );
  57. HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc );
  58. HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc );
  59. void    CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime );
  60. void    CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime );
  61. LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing );
  62. void    CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown  );
  63. void    CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl );
  64. void    CALLBACK OnLostDevice();
  65. void    CALLBACK OnDestroyDevice();
  66.  
  67. void    InitApp();
  68. HRESULT LoadMesh( IDirect3DDevice9* pd3dDevice, WCHAR* strFileName, ID3DXMesh** ppMesh );
  69. void    RenderText();
  70.  
  71.  
  72. //--------------------------------------------------------------------------------------
  73. // Entry point to the program. Initializes everything and goes into a message processing 
  74. // loop. Idle time is used to render the scene.
  75. //--------------------------------------------------------------------------------------
  76. INT WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
  77. {
  78.     // Set the callback functions. These functions allow the sample framework to notify
  79.     // the application about device changes, user input, and windows messages.  The 
  80.     // callbacks are optional so you need only set callbacks for events you're interested 
  81.     // in. However, if you don't handle the device reset/lost callbacks then the sample 
  82.     // framework won't be able to reset your device since the application must first 
  83.     // release all device resources before resetting.  Likewise, if you don't handle the 
  84.     // device created/destroyed callbacks then the sample framework won't be able to 
  85.     // recreate your device resources.
  86.     DXUTSetCallbackDeviceCreated( OnCreateDevice );
  87.     DXUTSetCallbackDeviceReset( OnResetDevice );
  88.     DXUTSetCallbackDeviceLost( OnLostDevice );
  89.     DXUTSetCallbackDeviceDestroyed( OnDestroyDevice );
  90.     DXUTSetCallbackMsgProc( MsgProc );
  91.     DXUTSetCallbackKeyboard( KeyboardProc );
  92.     DXUTSetCallbackFrameRender( OnFrameRender );
  93.     DXUTSetCallbackFrameMove( OnFrameMove );
  94.  
  95.     // Show the cursor and clip it when in full screen
  96.     DXUTSetCursorSettings( true, true );
  97.  
  98.     InitApp();
  99.  
  100.     // Initialize the sample framework and create the desired Win32 window and Direct3D 
  101.     // device for the application. Calling each of these functions is optional, but they
  102.     // allow you to set several options which control the behavior of the framework.
  103.     DXUTInit( true, true, true ); // Parse the command line, handle the default hotkeys, and show msgboxes
  104.     DXUTCreateWindow( L"HLSLwithoutEffects" );
  105.     DXUTCreateDevice( D3DADAPTER_DEFAULT, true, 640, 480, IsDeviceAcceptable, ModifyDeviceSettings );
  106.  
  107.     // Pass control to the sample framework for handling the message pump and 
  108.     // dispatching render calls. The sample framework will call your FrameMove 
  109.     // and FrameRender callback when there is idle time between handling window messages.
  110.     DXUTMainLoop();
  111.  
  112.     // Perform any application-level cleanup here. Direct3D device resources are released within the
  113.     // appropriate callback functions and therefore don't require any cleanup code here.
  114.  
  115.     return DXUTGetExitCode();
  116. }
  117.  
  118.  
  119. //--------------------------------------------------------------------------------------
  120. // Initialize the app 
  121. //--------------------------------------------------------------------------------------
  122. void InitApp()
  123. {
  124.     // Initialize dialogs
  125.     g_HUD.SetCallback( OnGUIEvent ); int iY = 10; 
  126.     g_HUD.AddButton( IDC_TOGGLEFULLSCREEN, L"Toggle full screen", 35, iY, 125, 22 );
  127.     g_HUD.AddButton( IDC_TOGGLEREF, L"Toggle REF (F3)", 35, iY += 24, 125, 22 );
  128.     g_HUD.AddButton( IDC_CHANGEDEVICE, L"Change device (F2)", 35, iY += 24, 125, 22 );
  129. }
  130.  
  131.  
  132. //--------------------------------------------------------------------------------------
  133. // Called during device initialization, this code checks the device for some 
  134. // minimum set of capabilities, and rejects those that don't pass by returning false.
  135. //--------------------------------------------------------------------------------------
  136. bool CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, 
  137.                                   D3DFORMAT BackBufferFormat, bool bWindowed )
  138. {
  139.     // Skip backbuffer formats that don't support alpha blending
  140.     IDirect3D9* pD3D = DXUTGetD3DObject(); 
  141.     if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,
  142.                     AdapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, 
  143.                     D3DRTYPE_TEXTURE, BackBufferFormat ) ) )
  144.         return false;
  145.  
  146.     return true;
  147. }
  148.  
  149.  
  150. //--------------------------------------------------------------------------------------
  151. // This callback function is called immediately before a device is created to allow the 
  152. // application to modify the device settings. The supplied pDeviceSettings parameter 
  153. // contains the settings that the framework has selected for the new device, and the 
  154. // application can make any desired changes directly to this structure.  Note however that 
  155. // the sample framework will not correct invalid device settings so care must be taken 
  156. // to return valid device settings, otherwise IDirect3D9::CreateDevice() will fail.  
  157. //--------------------------------------------------------------------------------------
  158. void CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps )
  159. {
  160.     // If device doesn't support HW T&L or doesn't support 1.1 vertex shaders in HW 
  161.     // then switch to SWVP.
  162.     if( (pCaps->DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0 ||
  163.          pCaps->VertexShaderVersion < D3DVS_VERSION(1,1) )
  164.     {
  165.         pDeviceSettings->BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  166.     }
  167.     else
  168.     {
  169.         pDeviceSettings->BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
  170.     }
  171.  
  172.     // This application is designed to work on a pure device by not using 
  173.     // IDirect3D9::Get*() methods, so create a pure device if supported and using HWVP.
  174.     if ((pCaps->DevCaps & D3DDEVCAPS_PUREDEVICE) != 0 && 
  175.         (pDeviceSettings->BehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING) != 0 )
  176.         pDeviceSettings->BehaviorFlags |= D3DCREATE_PUREDEVICE;
  177.  
  178.     // Debugging vertex shaders requires either REF or software vertex processing 
  179.     // and debugging pixel shaders requires REF.  
  180. #ifdef DEBUG_VS
  181.     if( pDeviceSettings->DeviceType != D3DDEVTYPE_REF )
  182.     {
  183.         pDeviceSettings->BehaviorFlags &= ~D3DCREATE_HARDWARE_VERTEXPROCESSING;
  184.         pDeviceSettings->BehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  185.     }
  186. #endif
  187. #ifdef DEBUG_PS
  188.     pDeviceSettings->DeviceType = D3DDEVTYPE_REF;
  189. #endif
  190. }
  191.  
  192.  
  193. //--------------------------------------------------------------------------------------
  194. // This callback function will be called immediately after the Direct3D device has been 
  195. // created, which will happen during application initialization and windowed/full screen 
  196. // toggles. This is the best location to create D3DPOOL_MANAGED resources since these 
  197. // resources need to be reloaded whenever the device is destroyed. Resources created  
  198. // here should be released in the OnDestroyDevice callback. 
  199. //--------------------------------------------------------------------------------------
  200. HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
  201. {
  202.     HRESULT hr;
  203.  
  204.     // Initialize the font
  205.     V_RETURN( D3DXCreateFont( pd3dDevice, 15, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, 
  206.                          OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, 
  207.                          L"Arial", &g_pFont ) );
  208.  
  209.     // Create vertex shader
  210.     WCHAR        strPath[512];
  211.     LPD3DXBUFFER pCode;
  212.  
  213.     D3DVERTEXELEMENT9 decl[] =
  214.     {
  215.         { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
  216.         D3DDECL_END()
  217.     };
  218.  
  219.     V_RETURN( pd3dDevice->CreateVertexDeclaration( decl, &g_pVertexDeclaration ) );
  220.     
  221.     // Find the vertex shader file
  222.     V_RETURN( DXUTFindDXSDKMediaFileCch( strPath, 512, L"HLSLwithoutEffects.vsh" ) );
  223.     
  224.  
  225.     // Define DEBUG_VS and/or DEBUG_PS to debug vertex and/or pixel shaders with the 
  226.     // shader debugger. Debugging vertex shaders requires either REF or software vertex 
  227.     // processing, and debugging pixel shaders requires REF.  The 
  228.     // D3DXSHADER_FORCE_*_SOFTWARE_NOOPT flag improves the debug experience in the 
  229.     // shader debugger.  It enables source level debugging, prevents instruction 
  230.     // reordering, prevents dead code elimination, and forces the compiler to compile 
  231.     // against the next higher available software target, which ensures that the 
  232.     // unoptimized shaders do not exceed the shader model limitations.  Setting these 
  233.     // flags will cause slower rendering since the shaders will be unoptimized and 
  234.     // forced into software.  See the DirectX documentation for more information about 
  235.     // using the shader debugger.
  236.     DWORD dwShaderFlags = 0;
  237.     #ifdef DEBUG_VS
  238.         dwShaderFlags |= D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT;
  239.     #endif
  240.     #ifdef DEBUG_PS
  241.         dwShaderFlags |= D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT;
  242.     #endif
  243.  
  244.     // Assemble the vertex shader from the file
  245.     V_RETURN( D3DXCompileShaderFromFile( strPath, NULL, NULL, "Ripple",
  246.                                          "vs_1_1", dwShaderFlags, &pCode,
  247.                                          NULL, &g_pConstantTable ) );
  248.  
  249.     // Create the vertex shader
  250.     hr = pd3dDevice->CreateVertexShader( (DWORD*)pCode->GetBufferPointer(),
  251.                                             &g_pVertexShader );
  252.     pCode->Release();
  253.     if( FAILED(hr) )
  254.         return DXTRACE_ERR( TEXT("CreateVertexShader"), hr );
  255.  
  256.  
  257.     // Setup the camera's view parameters
  258.     g_Camera.SetViewQuat( D3DXQUATERNION(-0.275f, 0.3f, 0.0f, 0.7f) );
  259.  
  260.  
  261.     return S_OK;
  262. }
  263.  
  264.  
  265. //--------------------------------------------------------------------------------------
  266. // This function loads the mesh and ensures the mesh has normals; it also optimizes the 
  267. // mesh for the graphics card's vertex cache, which improves performance by organizing 
  268. // the internal triangle list for less cache misses.
  269. //--------------------------------------------------------------------------------------
  270. HRESULT LoadMesh( IDirect3DDevice9* pd3dDevice, WCHAR* strFileName, ID3DXMesh** ppMesh )
  271. {
  272.     ID3DXMesh* pMesh = NULL;
  273.     WCHAR str[MAX_PATH];
  274.     HRESULT hr;
  275.  
  276.     // Load the mesh with D3DX and get back a ID3DXMesh*.  For this
  277.     // sample we'll ignore the X file's embedded materials since we know 
  278.     // exactly the model we're loading.  See the mesh samples such as
  279.     // "OptimizedMesh" for a more generic mesh loading example.
  280.     V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, strFileName ) );
  281.  
  282.     V_RETURN( D3DXLoadMeshFromX(str, D3DXMESH_MANAGED, pd3dDevice, NULL, NULL, NULL, NULL, &pMesh) );
  283.  
  284.     DWORD *rgdwAdjacency = NULL;
  285.  
  286.     // Make sure there are normals which are required for lighting
  287.     if( !(pMesh->GetFVF() & D3DFVF_NORMAL) )
  288.     {
  289.         ID3DXMesh* pTempMesh;
  290.         V( pMesh->CloneMeshFVF( pMesh->GetOptions(), 
  291.                                   pMesh->GetFVF() | D3DFVF_NORMAL, 
  292.                                   pd3dDevice, &pTempMesh ) );
  293.         V( D3DXComputeNormals( pTempMesh, NULL ) );
  294.  
  295.         SAFE_RELEASE( pMesh );
  296.         pMesh = pTempMesh;
  297.     }
  298.  
  299.     // Optimize the mesh for this graphics card's vertex cache 
  300.     // so when rendering the mesh's triangle list the vertices will 
  301.     // cache hit more often so it won't have to re-execute the vertex shader 
  302.     // on those vertices so it will improve perf.     
  303.     rgdwAdjacency = new DWORD[pMesh->GetNumFaces() * 3];
  304.     if( rgdwAdjacency == NULL )
  305.         return E_OUTOFMEMORY;
  306.     V( pMesh->ConvertPointRepsToAdjacency(NULL, rgdwAdjacency) );
  307.     V( pMesh->OptimizeInplace(D3DXMESHOPT_VERTEXCACHE, rgdwAdjacency, NULL, NULL, NULL) );
  308.     delete []rgdwAdjacency;
  309.  
  310.     *ppMesh = pMesh;
  311.  
  312.     return S_OK;
  313. }
  314.  
  315.  
  316. //--------------------------------------------------------------------------------------
  317. // This callback function will be called immediately after the Direct3D device has been 
  318. // reset, which will happen after a lost device scenario. This is the best location to 
  319. // create D3DPOOL_DEFAULT resources since these resources need to be reloaded whenever 
  320. // the device is lost. Resources created here should be released in the OnLostDevice 
  321. // callback. 
  322. //--------------------------------------------------------------------------------------
  323. HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, 
  324.                                 const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
  325. {
  326.     HRESULT hr;
  327.  
  328.     if( g_pFont )
  329.         V_RETURN( g_pFont->OnResetDevice() );
  330.     
  331.     // Create a sprite to help batch calls when drawing many lines of text
  332.     V_RETURN( D3DXCreateSprite( pd3dDevice, &g_pTextSprite ) );
  333.  
  334.     // Setup render states
  335.     pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
  336.     pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
  337.  
  338.     // Create and initialize index buffer
  339.     WORD* pIndices;
  340.  
  341.     V_RETURN( pd3dDevice->CreateIndexBuffer( g_dwNumIndices * sizeof(WORD),
  342.                                                0, D3DFMT_INDEX16,
  343.                                                D3DPOOL_DEFAULT, &g_pIB, NULL ) );
  344.  
  345.        
  346.     V_RETURN( g_pIB->Lock( 0, 0, (void**)&pIndices, 0 ) );
  347.  
  348.  
  349.     DWORD y;
  350.     for( y = 1; y < VERTS_PER_EDGE; y++ )
  351.     {
  352.         for( DWORD x = 1; x < VERTS_PER_EDGE; x++ )
  353.         {
  354.             *pIndices++ = (WORD)( (y-1)*VERTS_PER_EDGE + (x-1) );
  355.             *pIndices++ = (WORD)( (y-0)*VERTS_PER_EDGE + (x-1) );
  356.             *pIndices++ = (WORD)( (y-1)*VERTS_PER_EDGE + (x-0) );
  357.  
  358.             *pIndices++ = (WORD)( (y-1)*VERTS_PER_EDGE + (x-0) );
  359.             *pIndices++ = (WORD)( (y-0)*VERTS_PER_EDGE + (x-1) );
  360.             *pIndices++ = (WORD)( (y-0)*VERTS_PER_EDGE + (x-0) );
  361.         }
  362.     }
  363.  
  364.     V_RETURN( g_pIB->Unlock() );
  365.  
  366.     // Create and initialize vertex buffer
  367.     V_RETURN( pd3dDevice->CreateVertexBuffer( g_dwNumVertices * sizeof(D3DXVECTOR2),
  368.                                                 0, 0,
  369.                                                  D3DPOOL_DEFAULT, &g_pVB, NULL ) );
  370.  
  371.     D3DXVECTOR2 *pVertices;
  372.     V_RETURN( g_pVB->Lock( 0, 0, (void**)&pVertices, 0 ) );
  373.  
  374.     for( y = 0; y < VERTS_PER_EDGE; y++ )
  375.     {
  376.         for( DWORD x = 0; x < VERTS_PER_EDGE; x++ )
  377.         {
  378.             *pVertices++ = D3DXVECTOR2( ((float)x / (float)(VERTS_PER_EDGE-1) - 0.5f) * D3DX_PI,
  379.                                         ((float)y / (float)(VERTS_PER_EDGE-1) - 0.5f) * D3DX_PI );
  380.         }
  381.     }
  382.  
  383.     V_RETURN( hr = g_pVB->Unlock() );
  384.  
  385.  
  386.     // Setup the camera's projection parameters
  387.     float fAspectRatio = pBackBufferSurfaceDesc->Width / (FLOAT)pBackBufferSurfaceDesc->Height;
  388.     g_Camera.SetProjParams( D3DX_PI/4, fAspectRatio, 0.1f, 1000.0f );
  389.     g_Camera.SetWindow( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height );
  390.  
  391.     g_HUD.SetLocation( pBackBufferSurfaceDesc->Width-170, 0 );
  392.     g_HUD.SetSize( 170, 170 );
  393.     
  394.     return S_OK;
  395. }
  396.  
  397.  
  398. //--------------------------------------------------------------------------------------
  399. // This callback function will be called once at the beginning of every frame. This is the
  400. // best location for your application to handle updates to the scene, but is not 
  401. // intended to contain actual rendering calls, which should instead be placed in the 
  402. // OnFrameRender callback.  
  403. //--------------------------------------------------------------------------------------
  404. void CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime )
  405. {
  406.     // Update the camera's position based on user input 
  407.     g_Camera.FrameMove( fElapsedTime );
  408.  
  409.     // Set up the vertex shader constants
  410.     D3DXMATRIXA16 mWorldViewProj;
  411.     D3DXMATRIXA16 mWorld;
  412.     D3DXMATRIXA16 mView;
  413.     D3DXMATRIXA16 mProj;
  414.  
  415.     mWorld = *g_Camera.GetWorldMatrix();
  416.     mView  = *g_Camera.GetViewMatrix();
  417.     mProj  = *g_Camera.GetProjMatrix();
  418.  
  419.     mWorldViewProj = mWorld * mView * mProj;
  420.  
  421.     g_pConstantTable->SetMatrix( pd3dDevice, "mWorldViewProj", &mWorldViewProj );
  422.     g_pConstantTable->SetFloat( pd3dDevice, "fTime", (float) fTime );
  423. }
  424.  
  425.  
  426. //--------------------------------------------------------------------------------------
  427. // This callback function will be called at the end of every frame to perform all the 
  428. // rendering calls for the scene, and it will also be called if the window needs to be 
  429. // repainted. After this function has returned, the sample framework will call 
  430. // IDirect3DDevice9::Present to display the contents of the next buffer in the swap chain
  431. //--------------------------------------------------------------------------------------
  432. void CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime )
  433. {
  434.     HRESULT hr;
  435.      
  436.     // Clear the render target and the zbuffer 
  437.     V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 45, 50, 170), 1.0f, 0) );
  438.  
  439.     // Render the scene
  440.     if( SUCCEEDED( pd3dDevice->BeginScene() ) )
  441.     {
  442.         pd3dDevice->SetVertexDeclaration( g_pVertexDeclaration );
  443.         pd3dDevice->SetVertexShader( g_pVertexShader );
  444.         pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(D3DXVECTOR2) );
  445.         pd3dDevice->SetIndices( g_pIB );
  446.  
  447.         V( pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, g_dwNumVertices,
  448.                                              0, g_dwNumIndices/3 ) );
  449.         
  450.         RenderText();
  451.         V( g_HUD.OnRender( fElapsedTime ) );
  452.         
  453.         V( pd3dDevice->EndScene() );
  454.     }
  455. }
  456.  
  457.  
  458. //--------------------------------------------------------------------------------------
  459. // Render the help and statistics text. This function uses the ID3DXFont interface for 
  460. // efficient text rendering.
  461. //--------------------------------------------------------------------------------------
  462. void RenderText()
  463. {
  464.     // The helper object simply helps keep track of text position, and color
  465.     // and then it calls pFont->DrawText( g_pSprite, strMsg, -1, &rc, DT_NOCLIP, g_clr );
  466.     // If NULL is passed in as the sprite object, then it will work however the 
  467.     // pFont->DrawText() will not be batched together.  Batching calls will improves performance.
  468.     CDXUTTextHelper txtHelper( g_pFont, g_pTextSprite, 15 );
  469.  
  470.     // Output statistics
  471.     txtHelper.Begin();
  472.     txtHelper.SetInsertionPos( 5, 5 );
  473.     txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 0.0f, 1.0f ) );
  474.     txtHelper.DrawTextLine( DXUTGetFrameStats() );
  475.     txtHelper.DrawTextLine( DXUTGetDeviceStats() );
  476.  
  477.     txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) );
  478.     
  479.     // Draw help
  480.     if( g_bShowHelp )
  481.     {
  482.         const D3DSURFACE_DESC* pd3dsdBackBuffer = DXUTGetBackBufferSurfaceDesc();
  483.         txtHelper.SetInsertionPos( 10, pd3dsdBackBuffer->Height-15*6 );
  484.         txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 0.75f, 0.0f, 1.0f ) );
  485.         txtHelper.DrawTextLine( L"Controls (F1 to hide):" );
  486.  
  487.         txtHelper.SetInsertionPos( 40, pd3dsdBackBuffer->Height-15*5 );
  488.         txtHelper.DrawTextLine( L"Rotate model: Left mouse button\n"
  489.                                 L"Rotate camera: Right mouse button\n"
  490.                                 L"Zoom camera: Mouse wheel scroll\n"
  491.                                 L"Hide help: F1" );                                      
  492.     }
  493.     else
  494.     {
  495.         txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) );
  496.         txtHelper.DrawTextLine( L"Press F1 for help" );
  497.     }
  498.     txtHelper.End();
  499. }
  500.  
  501.  
  502. //--------------------------------------------------------------------------------------
  503. // Before handling window messages, the sample framework passes incoming windows 
  504. // messages to the application through this callback function. If the application sets 
  505. // *pbNoFurtherProcessing to TRUE, then the sample framework will not process this message.
  506. //--------------------------------------------------------------------------------------
  507. LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing )
  508. {
  509.     // Give the dialogs a chance to handle the message first
  510.     *pbNoFurtherProcessing = g_HUD.MsgProc( hWnd, uMsg, wParam, lParam );
  511.     if( *pbNoFurtherProcessing )
  512.         return 0;
  513.     
  514.     // Pass all remaining windows messages to camera so it can respond to user input
  515.     g_Camera.HandleMessages( hWnd, uMsg, wParam, lParam );
  516.  
  517.     return 0;
  518. }
  519.  
  520.  
  521. //--------------------------------------------------------------------------------------
  522. // As a convenience, the sample framework inspects the incoming windows messages for
  523. // keystroke messages and decodes the message parameters to pass relevant keyboard
  524. // messages to the application.  The framework does not remove the underlying keystroke 
  525. // messages, which are still passed to the application's MsgProc callback.
  526. //--------------------------------------------------------------------------------------
  527. void CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown )
  528. {
  529.     if( bKeyDown )
  530.     {
  531.         switch( nChar )
  532.         {
  533.             case VK_F1: g_bShowHelp = !g_bShowHelp; break;
  534.         }
  535.     }
  536. }
  537.  
  538.  
  539. //--------------------------------------------------------------------------------------
  540. // Handles the GUI events
  541. //--------------------------------------------------------------------------------------
  542. void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl )
  543. {
  544.     switch( nControlID )
  545.     {
  546.         case IDC_TOGGLEFULLSCREEN: DXUTToggleFullScreen(); break;
  547.         case IDC_TOGGLEREF:        DXUTToggleREF(); break;
  548.         case IDC_CHANGEDEVICE:     DXUTSetShowSettingsDialog( !DXUTGetShowSettingsDialog() ); break;
  549.     }
  550. }
  551.  
  552.  
  553. //--------------------------------------------------------------------------------------
  554. // This callback function will be called immediately after the Direct3D device has 
  555. // entered a lost state and before IDirect3DDevice9::Reset is called. Resources created
  556. // in the OnResetDevice callback should be released here, which generally includes all 
  557. // D3DPOOL_DEFAULT resources. See the "Lost Devices" section of the documentation for 
  558. // information about lost devices.
  559. //--------------------------------------------------------------------------------------
  560. void CALLBACK OnLostDevice()
  561. {
  562.     if( g_pFont )
  563.         g_pFont->OnLostDevice();
  564.     
  565.     SAFE_RELEASE( g_pIB );
  566.     SAFE_RELEASE( g_pVB );
  567.     SAFE_RELEASE( g_pTextSprite );
  568. }
  569.  
  570.  
  571. //--------------------------------------------------------------------------------------
  572. // This callback function will be called immediately after the Direct3D device has 
  573. // been destroyed, which generally happens as a result of application termination or 
  574. // windowed/full screen toggles. Resources created in the OnCreateDevice callback 
  575. // should be released here, which generally includes all D3DPOOL_MANAGED resources. 
  576. //--------------------------------------------------------------------------------------
  577. void CALLBACK OnDestroyDevice()
  578. {
  579.     SAFE_RELEASE( g_pFont );
  580.     SAFE_RELEASE( g_pVertexShader );
  581.     SAFE_RELEASE( g_pConstantTable );
  582.     SAFE_RELEASE( g_pVertexDeclaration );
  583. }
  584.  
  585.  
  586.  
  587.